package 综合练习线程;

/**
 * @作者:侯国威
 * @时间: 2020/4/12/13:07
 * @邮箱:1045077189@qq.com 题目：
 * 生产者将产品交给店员，消费者从店员处取走产品，i店员再一次只能持有固定数量的产品，
 * 如果生产者视图生产更多的产品，店员会叫生产者停一下，如果店员中有空位房产品了再通知u
 * 生产者继续生产；如果店员没有产品了，店员会告诉消费这一下，如果店员有产品了再通知消费者来取走产品
 * <p>
 * 出现的线程安全问题：
 * 生产者比消费者快时，消费者会漏洞安一些数据没有取到；
 * 消费者比生产者快时，消费者回去相同的数据
 * 分析：
 * 1、具有两个线程 生产者，消费者
 * 2、共享数据店员（产品数量）
 * 3、解决线程安全：三种方法。同步机制
 * 4、涉及到线程通信
 */

public class Productor_test {
    public static void main(String[] args) {
        Clerk clerk = new Clerk();//唯一的
        Produtor produtor = new Produtor(clerk);
        produtor.setName("生产者1");
        produtor.start();
        Consumer consumer = new Consumer(clerk);
        consumer.setName("消费者1");
        consumer.start();
        Consumer consumer2 = new Consumer(clerk);
        consumer2.setName("消费者2");
        consumer2.start();
    }
}

class Clerk {
    /**
     * @作者:侯国威
     * @时间：2020/4/12_13:57
     * @描述:店员（共享数据）
     */

    private int count=0;
    public synchronized void production() throws InterruptedException {
        //生产产品
        if (count<20){
            count++;
            //中途有可能发生阻塞，线程安全问题

            System.out.println(Thread.currentThread().getName()+":开始第"+count+"生产产品");
            notify();
        }else {
            //
            wait();
        }
    }

    public synchronized void consumerProduct() throws InterruptedException {
        //消费产品
        if (count>0){
            System.out.println(Thread.currentThread().getName()+":开始消费"+count+"个产品");
            count--;
            notify();
        }else {
            wait();
        }
    }

}

class Produtor extends Thread {
    /**
     * @作者:侯国威
     * @时间：2020/4/12_13:59
     * @描述:生产者
     */
    private Clerk clerk;

    public Produtor(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        System.out.println(getName() + ":开始生产产品");
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                clerk.production();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

class Consumer extends Thread {
    /**
     * @作者:侯国威
     * @时间：2020/4/12_14:01
     * @描述:消费者
     */
    private Clerk clerk;

    public Consumer(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        System.out.println(getName() + ":开始消费");
        while (true) {
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                clerk.consumerProduct();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}


